package com.lu.aspect;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author luke
 * @className WebLogAspect
 * @description 据说Around是阻塞式的的处理方式，
 * @date 2021/07/13 16:38
 */
@Aspect
@Configuration
@Slf4j
public class WebLogAspect {

    ObjectMapper objectMapper = new ObjectMapper();

    /**
    * @description 指定包类中所有所有方法为连接点
    * @author luke
    * @date 2021/7/13 16:40
    * @return
    */
    @Pointcut("execution(* com.lu.controller..*.*(..))")
    public void webLog(){}

    /**
    * @description 环绕通知
    * @author luke
    * @date 2021/7/13 16:42
    * @return java.lang.Object
    */
    @Around("webLog()")
    public Object webLogAround(ProceedingJoinPoint joinPoint) throws Throwable {

        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();
        log.info("==========> 请求URI:{}",request.getRequestURI());

        String className = joinPoint.getTarget().getClass().getName();
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        String methodName = new StringBuffer(className)
                .append(".")
                .append(signature.getMethod().getName())
                .append("():").toString();

        //手动处理打印报错的请求类型
        Map<String,Object> paramMap = new LinkedHashMap<>(8);
        Object[] args = joinPoint.getArgs();
        String[] parameterNames = signature.getParameterNames();
        //参数名和参数值，顺序是一致的
        for(int i = 0; i < args.length; i++) {
            if(args[i] instanceof HttpServletResponse) {
                continue;
            }else if(args[i] instanceof HttpServletRequest) {
                continue;
            }else if(args[i] instanceof MultipartFile) {
                paramMap.put(parameterNames[i], "upload file size:" + ((MultipartFile)args[i]).getSize());
            }else {
                paramMap.put(parameterNames[i], args[i]);
            }
        }
        log.info("==========> {} 方法原始报文:{}",methodName,objectMapper.writeValueAsString(paramMap));
        Object proceed = joinPoint.proceed();
        log.info("==========> {} 方法响应报文:{}",methodName,objectMapper.writeValueAsString(proceed));
        return proceed;
    }








}
